package org.yak.core.nosql;

import java.io.File;
import java.io.FileInputStream;
import java.net.URLDecoder;
import java.util.Properties;
import java.util.Set;

import org.apache.log4j.Logger;
import org.yak.core.utils.SerializeUtil;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 *
 * @平台：FAMSUN统一开发平台
 * @文件名称：RedisCacheConfig.java
 * @文件描述：redis缓存工具类
 * @author xq
 * @日期：2017年11月8日下午4:08:17
 *
 */
public class RedisCacheConfig{

	private static final Logger logger = Logger.getLogger(RedisCacheConfig.class);

	/**
	 * redis连接池
	 */
	private static JedisPool jedisPool;

	/**
	 * 默认使用第一个数据库片区
	 */
	private static int redis_database_index=0;

	static{
		JedisPoolConfig config = new JedisPoolConfig();
		try{
			String redisPath = Thread.currentThread().getContextClassLoader().getResource("/redis.properties").getPath();
			redisPath = URLDecoder.decode(redisPath, "UTF-8");
        	logger.error("redisPath地址："+redisPath);
			//String redisPath = "E:\\workspace\\famsun-fpds-workspace\\famsun-framework\\yak\\yak-common\\src\\main\\resources\\redis.properties";
			File file = new File(redisPath);
			if(file.exists()){
				Properties pro = new Properties();
				pro.load(new FileInputStream(file));

				//最大连接数
				config.setMaxTotal(Integer.valueOf(pro.getProperty("redis.pool.maxTotal")));
				//最大空闲连接数
				config.setMaxIdle(Integer.valueOf(pro.getProperty("redis.pool.maxIdle")));
				//最小空闲数
				config.setMinIdle(Integer.valueOf(pro.getProperty("redis.pool.minIdle")));
				//获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1
				config.setMaxWaitMillis(Long.valueOf(pro.getProperty("redis.pool.maxWaitMillis")));
				//在获取连接的时候检查有效性, 默认false
				config.setTestOnBorrow(Boolean.valueOf(pro.getProperty("redis.pool.testOnBorrow")));
				//在获取返回结果的时候检查有效性, 默认false
				config.setTestOnReturn(Boolean.valueOf(pro.getProperty("redis.pool.testOnReturn")));
				config.setTestWhileIdle(true);
				//读取数据库片区
				redis_database_index = Integer.parseInt(pro.getProperty("redis.database"));
				//读取地址
				String host = pro.getProperty("redis.ip");
				int port = Integer.parseInt(pro.getProperty("redis.port"));
				int timeout = Integer.parseInt(pro.getProperty("redis.timeout"));
				//String auth = pro.getProperty("redis.auth");
				jedisPool = new JedisPool(config, host, port, timeout);
				logger.info("redis缓存服务连接成功......200!");
			}else{
				logger.error("找不到redis配置文件，系统不提供redis缓存服务");
			}

		}catch(Exception e){
			logger.error("加载redis缓存服务异常",e);
		}

	}

	/**
	 *
	 * @方法没描述：获取Jedis实例
	 * @author xq
	 * @return
	 */
	public static Jedis getJedis() {
		try {
             if (jedisPool != null) {
            	 Jedis jedis = jedisPool.getResource();
            	 //设置默认库索引
            	 int old_database_index = jedis.getDB().intValue();
            	 if(redis_database_index != old_database_index){
            		 jedis.select(redis_database_index);
            	 }
                 return jedis;
             } else {
            	 logger.error("redis连接池不存在");
                 return null;
             }
         } catch (Exception e) {
        	 logger.error("redis服务不可用，获取缓存连接池失败，连接缓存服务器失败:",e);
             return null;
         }
	}

	/**
	 * 获取jedis数据库，
	 * @方法没描述：
	 * @author XQ
	 * @param database_index
	 * @return
	 */
	public static Jedis getJedis(int database_index) {
		try {
             if (jedisPool != null) {
            	 Jedis jedis = jedisPool.getResource();
            	 //获取上一次设置的数据库索引
            	 int old_database_index = jedis.getDB().intValue();
            	 if(database_index != old_database_index){
            		 jedis.select(database_index);
            	 }
                 return jedis;
             } else {
            	 logger.error("redis连接池不存在");
                 return null;
             }
         } catch (Exception e) {
        	 logger.error("redis服务不可用，获取缓存连接池失败，连接缓存服务器失败:",e);
             return null;
         }
	}

	/**
	 *
	 * @方法没描述：添加内容,用不过期
	 * @author Administrator
	 * @param key
	 * @param value
	 */
	public static void addStr(int database_index,String key,String value){
		Jedis jedis = getJedis(database_index);
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			if(exists(database_index,key)){
				//logger.debug(key+",相关内容已经存在，系统将重新设置新的值");
				jedis.del(key);
			}
			jedis.set(key, value);
		}
		closeConnect(jedis);
	}

	public static void addStr(String key,String value){
		Jedis jedis = getJedis();
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			if(exists(key)){
				//logger.debug(key+",相关内容已经存在，系统将重新设置新的值");
				jedis.del(key);
			}
			jedis.set(key, value);
		}
		closeConnect(jedis);
	}

	/**
	 *
	 * @方法没描述：添加有时限的内容
	 * @author xq
	 * @param key
	 * @param value
	 * @param expire 时间秒，过期时间
	 */
	public static void addStr(String key,String value,int expire){
		Jedis jedis = getJedis();
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			jedis.setex(key, expire,value);
		}
		closeConnect(jedis);
	}

	/**
	 *
	 * @方法没描述：对已经存在的值追加字符串
	 * @author xq
	 * @param key
	 * @param value
	 */
	public static void appendStr(String key,String value){
		Jedis jedis = getJedis();
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			jedis.append(key, value);
		}
        closeConnect(jedis);
	}

	/**
	 *
	 * @方法没描述：对已经存在的值追加字符串
	 * @author xq
	 * @param key
	 * @param value
	 */
	public static void appendStr(int database_index,String key,String value){
		Jedis jedis = getJedis(database_index);
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			jedis.append(key, value);
		}
       closeConnect(jedis);
	}

	/**
	 *
	 * @方法没描述：获取key
	 * @author xq
	 * @param key
	 * @return
	 */
	public static String getStr(String key){
		String str = null;
		Jedis jedis = getJedis();
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			if(exists(key)){
				str = jedis.get(key);
			}else{
				logger.debug(key+",存储对象不存在");
			}
		}
		closeConnect(jedis);
		return new String(str);
	}

	/**
	 *
	 * @方法没描述：删除缓存数据
	 * @author xq
	 * @param key
	 * @return
	 */
	public static boolean del(int database_index,String key){
		boolean bool = false;
		Jedis jedis = getJedis(database_index);
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			if(exists(database_index,key)){
				jedis.del(key);
				bool = true;
			}else{
				logger.debug(key+",不存在，系统无法删除");
			}
		}
		closeConnect(jedis);
		return bool;
	}

	public static boolean del(String key){
		boolean bool = false;
		Jedis jedis = getJedis();
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			if(exists(key)){
				jedis.del(key);
				bool = true;
			}else{
				logger.debug(key+",不存在，系统无法删除");
			}
		}
		closeConnect(jedis);
		return bool;
	}

	/**
	 *
	 * @方法没描述：添加对象
	 * @author xq
	 * @param key
	 * @param obj
	 */
	public static void add(String key,Object obj){
		Jedis jedis = getJedis();
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			if(exists(key)){
				//logger.debug(key+",相关内容已经存在，系统将重新设置新的值");
				jedis.del(key);
			}
			byte[] value = SerializeUtil.serialize(obj);
			jedis.set(key.getBytes(), value);
		}
		closeConnect(jedis);
	}

	public static void add(int database_index,String key,Object obj){
		Jedis jedis = getJedis(database_index);
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			if(exists(database_index,key)){
				//logger.debug(key+",相关内容已经存在，系统将重新设置新的值");
				jedis.del(key);
			}
			byte[] value = SerializeUtil.serialize(obj);
			jedis.set(key.getBytes(), value);
		}
		closeConnect(jedis);
	}

	/**
	 *
	 * @方法没描述：添加对象
	 * @author xq
	 * @param key
	 * @param obj
	 * @param expire 超时时间秒 1->1秒
	 */
	public static void add(String key,Object obj,int expire){
		Jedis jedis = getJedis();
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			if(exists(key)){
				//logger.debug(key+",相关内容已经存在，系统将重新设置新的值");
				jedis.del(key);
			}
			byte[] value = SerializeUtil.serialize(obj);
			jedis.setex(key.getBytes(), expire,value);
		}
		closeConnect(jedis);
	}

	/**
	 *
	 * @方法没描述：获取对象
	 * @author xq
	 * @param key
	 * @return
	 */
	public static Object get(String key){
		Object obj = null;
		Jedis jedis = getJedis();
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			if(exists(key)){
				byte[] value = jedis.get(key.getBytes());
				obj = SerializeUtil.unserialize(value);
			}else{
				logger.debug(key+",存储对象不存在");
			}
		}
		closeConnect(jedis);
		return obj;
	}

	public static Object get(int database_index,String key){
		Object obj = null;
		Jedis jedis = getJedis(database_index);
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			if(exists(database_index,key)){
				byte[] value = jedis.get(key.getBytes());
				obj = SerializeUtil.unserialize(value);
			}else{
				logger.debug(key+",存储对象不存在");
			}
		}
		closeConnect(jedis);
		return obj;
	}

	/**
	 *
	 * @方法没描述：判断key是否存在
	 * @author xq
	 * @param key
	 * @return
	 */
	public static boolean exists(String key){
		boolean flag = false;
		Jedis jedis = getJedis();
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			flag = jedis.exists(key);
		}
        closeConnect(jedis);
        return flag;
	}

	public static boolean exists(int database_index,String key){
		boolean flag = false;
		Jedis jedis = getJedis(database_index);
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			flag = jedis.exists(key);
		}
        closeConnect(jedis);
        return flag;
	}

	/**
	 *
	 * @方法没描述：清空当前数据缓存
	 * @author xq
	 */
	public static void clearDB(){
		Jedis jedis = getJedis();
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			jedis.flushDB();
		}
		closeConnect(jedis);
	}

	public static void clearDB(int database_index){
		Jedis jedis = getJedis(database_index);
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			jedis.flushDB();
		}
		closeConnect(jedis);
	}

	/**
	 *
	 * @方法没描述：清空所有缓存
	 * @author xq
	 */
	public static void clearCache(){
		Jedis jedis = getJedis();
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
		}else{
			jedis.flushAll();
		}
		closeConnect(jedis);
	}

	/**
	 *
	 * @方法没描述：获取redis的所有的key
	 * @author xq
	 * @return
	 */
	public static Set<String> getAllKeys(){
		Jedis jedis = getJedis();
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
			closeConnect(jedis);
			return null;
		}
		Set<String> list = jedis.keys("*");
		closeConnect(jedis);
		return list;
	}

	public static Set<String> getAllKeys(int database_index){
		Jedis jedis = getJedis(database_index);
		if(jedis ==null){
			logger.debug("redis服务不可用，连接缓存服务器失败");
			closeConnect(jedis);
			return null;
		}
		Set<String> list = jedis.keys("*");
		closeConnect(jedis);
		return list;
	}

	/**
	  * 释放jedis资源
	  * @param jedis
	  */
	 public static void closeConnect(final Jedis jedis) {
	     if (jedis != null) {
	    	 jedis.close();
	     }
	 }



	 /**
	  *
	  * @方法没描述：测试
	  * @author xq
	  * @param args
	  */
	 public static void main(String args[]){
		 /*int i=0;
		 while(true){
			 Map<String,Object> param = new HashMap<String,Object>();
			 param.put("name", "nihao_"+i);
			 RedisCacheConfig.add("test", param);
			 Object obj = RedisCacheConfig.get("test");
			 System.out.println(obj+"------------>");
			 i++;
		 }*/
		 //RedisCacheConfig.addStr("1", "你好");
		 //System.out.println(RedisCacheConfig.getStr("1"));
	 }
}
